Skip to content

buffer: improve performance of multiple Buffer operations#61871

Open
thisalihassan wants to merge 10 commits intonodejs:mainfrom
thisalihassan:buffer-perf-improvements
Open

buffer: improve performance of multiple Buffer operations#61871
thisalihassan wants to merge 10 commits intonodejs:mainfrom
thisalihassan:buffer-perf-improvements

Conversation

@thisalihassan
Copy link
Contributor

@thisalihassan thisalihassan commented Feb 17, 2026

Multiple performance improvements to Buffer operations, verified with benchmarks (15-30 runs, comparing old vs new binaries built from same tree).

Buffer.copyBytesFrom() (+100-210%)
Avoid intermediate TypedArrayPrototypeSlice allocation by calculating byte offsets directly into the source TypedArray's underlying ArrayBuffer.

Buffer.prototype.fill("t", "ascii") (+26-37%)

ASCII indexOf (+14-46%)
Call indexOfString directly for ASCII encoding instead of first converting the search value to a Buffer via fromStringFast and then calling indexOfBuffer. ASCII and Latin-1 share the same byte values for characters 0-127.

swap16/32/64 (+3-38%)
Add V8 Fast API C++ functions (FastSwap16/32/64) alongside the existing slow path. Largest gains at len=256 (+35%).

Benchmark results

Key results (15-30 runs, *** = p < 0.001):

Benchmark Improvement
copyBytesFrom (offset, Uint8Array, len=256) +210% ***
copyBytesFrom (offset+length, Uint8Array, len=256) +206% ***
swap16 len=256 +38% ***
fill("t", "ascii") size=8192 +37% ***
indexOf ASCII 'Alice' +46% ***
indexOf ASCII '@' +31% ***
fill("t", "ascii") size=65536 +26% ***
swap64 len=768 aligned +12% ***

Attaching Details below:
detail.pdf -- visual breakdown
buffer-benchmark-all-rebased.csv -- raw benchmark CSV
compare-R-output.txt-- full output

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/performance

@nodejs-github-bot nodejs-github-bot added buffer Issues and PRs related to the buffer subsystem. c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run. labels Feb 17, 2026
@thisalihassan thisalihassan force-pushed the buffer-perf-improvements branch from d2ba38f to 495feb5 Compare February 17, 2026 21:41
Comment on lines +1210 to +1217
void FastSwap16(Local<Value> receiver,
Local<Value> buffer_obj,
// NOLINTNEXTLINE(runtime/references)
FastApiCallbackOptions& options) {
HandleScope scope(options.isolate);
ArrayBufferViewContents<char> buffer(buffer_obj);
CHECK(nbytes::SwapBytes16(const_cast<char*>(buffer.data()), buffer.length()));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These fast callbacks are non-identical to the conventional callbacks they shadow.

  • The existing callbacks validate their argument and throws to JS if invalid, whereas your fast callbacks hard-crash the process. It might be better to validate in the JS layer, then use the same unwrapping logic on both sides.
  • Your fast callback cannot have a different return convention to the conventional callback. You will need to remove the return value from the conventional callback.

Copy link
Member

@ChALkeR ChALkeR Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was removing the validation instead of moving it to js intentional?

Also fast paths can keep the validation and fall back to slow i think, so we can still validate on the src side?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also fast paths can keep the validation and fall back to slow i think, so we can still validate on the src side?

This is outdated, the fast API doesn't use fallback any more (since Node.js v23.x).

However, any validation in a JS wrapper should be shadowed by a CHECK or DCHECK in the C++ binding.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SPREAD_BUFFER_ARG already contains CHECK((val)->IsArrayBufferView()) on all Slow & Fast swap methods

Comment on lines +1210 to +1217
void FastSwap16(Local<Value> receiver,
Local<Value> buffer_obj,
// NOLINTNEXTLINE(runtime/references)
FastApiCallbackOptions& options) {
HandleScope scope(options.isolate);
ArrayBufferViewContents<char> buffer(buffer_obj);
CHECK(nbytes::SwapBytes16(const_cast<char*>(buffer.data()), buffer.length()));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fast callbacks should include debug tracking and call tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for sharing these I will update the code

@Renegade334 Renegade334 added performance Issues and PRs related to the performance of Node.js. needs-benchmark-ci PR that need a benchmark CI run. labels Feb 17, 2026
@codecov
Copy link

codecov bot commented Feb 17, 2026

Codecov Report

❌ Patch coverage is 91.76471% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.68%. Comparing base (7547e79) to head (f1d938b).

Files with missing lines Patch % Lines
src/node_buffer.cc 72.00% 0 Missing and 7 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #61871      +/-   ##
==========================================
- Coverage   91.60%   89.68%   -1.92%     
==========================================
  Files         337      676     +339     
  Lines      140745   206716   +65971     
  Branches    21802    39585   +17783     
==========================================
+ Hits       128925   185400   +56475     
- Misses      11595    13449    +1854     
- Partials      225     7867    +7642     
Files with missing lines Coverage Δ
lib/buffer.js 99.16% <100.00%> (+12.78%) ⬆️
src/node_buffer.cc 68.19% <72.00%> (ø)

... and 459 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@thisalihassan thisalihassan force-pushed the buffer-perf-improvements branch 4 times, most recently from 1395d2f to 01ba74f Compare February 17, 2026 23:42
FastApiCallbackOptions& options) {
TRACK_V8_FAST_API_CALL("buffer.swap16");
HandleScope scope(options.isolate);
ArrayBufferViewContents<char> buffer(buffer_obj);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ArrayBufferViewContents is wrong here, as buffer.data() may be a stack-allocated copy of the byte data rather than the data itself. SPREAD_BUFFER_ARG is the correct macro to use here, as per the conventional callback.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Renegade334 replaced ArrayBufferViewContents with SPREAD_BUFFER_ARG in all three fast swap callbacks

Copy link
Member

@ChALkeR ChALkeR left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For toHex, wait until #61609, which improves native perf significantly (more than Uint8Array.prototype.toHex)

See also #60249 (comment)

} else if (value.length === 1) {
// Fast path: If `value` fits into a single byte, use that numeric value.
if (normalizedEncoding === 'utf8') {
if (normalizedEncoding === 'utf8' || normalizedEncoding === 'ascii') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, ascii behaves exactly like latin1
Unsure if by design or accidentally

Copy link
Contributor Author

@thisalihassan thisalihassan Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this is safe by design I am just extending the existing single byte numeric optimization to cover ASCII, since the guard already constrains it to the valid ASCII range.

@thisalihassan
Copy link
Contributor Author

Note on toBase64 / toBase64url:

I also tried replacing the C++ base64Slice/base64urlSlice bindings with V8's Uint8Array.prototype.toBase64() (similar to the toHex change) but it caused a 35-54% regression across all buffer sizes so I reverted base64/base64url and kept only the toHex optimization which showed a clear +26-37% win.

@ChALkeR
Copy link
Member

ChALkeR commented Feb 18, 2026

@thisalihassan toHex doesn't show a win anymore with nbytes update which should soon land (as it landed in nbytes)

Instead, it's ~3x slower.

See nodejs/nbytes#12

@thisalihassan
Copy link
Contributor Author

thisalihassan commented Feb 18, 2026

Hi @ChALkeR thanks for flagging I was not aware. I benchmarked the nibble approach locally and it's indeed a much bigger win (~3x vs my ~30% with toHex). Reverted the toHex path entirely the other changes in this PR are unaffected.

Should I include the nbytes nibble HexEncode optimization in this PR or keep them as separate PRs?

PS: One test is failing /test/parallel/test-debugger-restart-message.js I believe it's known mac issue and unrelated to my changes

@thisalihassan
Copy link
Contributor Author

For toHex, wait until #61609, which improves native perf significantly (more than Uint8Array.prototype.toHex)

See also #60249 (comment)

Hi @ChALkeR I see that your changes landed, congratualtions on that huge win. Is there benchmark-ci that we can run on this PR? I can rebase it

@thisalihassan
Copy link
Contributor Author

thisalihassan commented Feb 24, 2026

I re-ran the benchmark against the latest main (which contains the nibble improvement) and found out there are few regressions caused by my code:

buffers/buffer-indexof.js n=50000 type='buffer' encoding='undefined' search='aaaaaaaaaaaaaaaaa' *** -9.41 %
buffers/buffer-indexof.js n=50000 type='string' encoding='ascii' search='aaaaaaaaaaaaaaaaa' *** -10.93
buffers/buffer-indexof.js n=50000 type='string' encoding='latin1' search='aaaaaaaaaaaaaaaaa' *** -9.44 %
buffers/buffer-indexof.js n=50000 type='string' encoding='utf8' search='aaaaaaaaaaaaaaaaa' *** -9.18 %

I tried fixing this regression but unavoidable

Attaching Details below:
detail.pdf -- visual breakdown

buffer-benchmark-all-rebased.csv -- raw benchmark CSV

@thisalihassan
Copy link
Contributor Author

thisalihassan commented Feb 24, 2026

compare-R-output.txt-- full output from Rscript benchmark/compare.R (shared as a file to avoid cluttering the PR comment).

@thisalihassan thisalihassan force-pushed the buffer-perf-improvements branch from 59f5d09 to 48abfc5 Compare February 27, 2026 23:09
@thisalihassan
Copy link
Contributor Author

PS: I resolved some conflicts

@thisalihassan
Copy link
Contributor Author

Hi @ChALkeR @anonrig @Renegade334 is this PR ready to land? can you also please check the latest benchmarks i have posted, I have compiled PDF for this benchmark in one my comments above for more detail

Screenshot 2026-03-01 at 2 29 23 AM Screenshot 2026-03-01 at 2 29 40 AM Screenshot 2026-03-01 at 2 29 54 AM Screenshot 2026-03-01 at 2 28 57 AM

Copy link
Member

@Qard Qard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally LGTM, but one small nit.

@RafaelGSS RafaelGSS added the request-ci Add this label to start a Jenkins CI on a PR. label Mar 11, 2026
@github-actions github-actions bot added request-ci-failed An error occurred while starting CI via request-ci label, and manual interventon is needed. and removed request-ci Add this label to start a Jenkins CI on a PR. labels Mar 11, 2026
@github-actions
Copy link
Contributor

Failed to start CI
   ⚠  Commits were pushed since the last approving review:
   ⚠  - buffer: improve performance of multiple Buffer operations
   ⚠  - buffer: address PR feedback
   ⚠  - buffer: revert toHex in favour of nbytes HexEncode update
   ⚠  - resolve feedback
   ⚠  - resolve feedback on fast callbacks
   ⚠  - added comments and updated tests
   ⚠  - resolve feedback
   ✘  Refusing to run CI on potentially unsafe PR
https://github.com/nodejs/node/actions/runs/22977319444

@aduh95 aduh95 added author ready PRs that have at least one approval, no pending requests for changes, and a CI started. request-ci Add this label to start a Jenkins CI on a PR. and removed request-ci-failed An error occurred while starting CI via request-ci label, and manual interventon is needed. labels Mar 17, 2026
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Mar 17, 2026
@nodejs-github-bot
Copy link
Collaborator

nodejs-github-bot commented Mar 17, 2026

CI: https://ci.nodejs.org/job/node-test-pull-request/71839/
Benchmark CI: https://ci.nodejs.org/view/Node.js%20benchmark/job/benchmark-node-micro-benchmarks/1811/

Results
confidence improvement accuracy (*)    (**)   (***)
buffers/buffer-atob.js n=1000000 size=128                                                                                                               **      3.04 %       ±1.92%  ±2.55%  ±3.32%
buffers/buffer-atob.js n=1000000 size=16                                                                                                                **      3.12 %       ±1.83%  ±2.44%  ±3.18%
buffers/buffer-atob.js n=1000000 size=64                                                                                                               ***      3.98 %       ±1.39%  ±1.85%  ±2.41%
buffers/buffer-base64-decode-wrapped.js n=32 linesCount=524288 charsPerLine=76                                                                           *      1.02 %       ±0.90%  ±1.21%  ±1.61%
buffers/buffer-bytelength-string.js n=4000000 repeat=1 encoding='base64' type='one_byte'                                                                 *      2.77 %       ±2.36%  ±3.13%  ±4.08%
buffers/buffer-bytelength-string.js n=4000000 repeat=1 encoding='utf8' type='four_bytes'                                                               ***      8.29 %       ±0.81%  ±1.08%  ±1.41%
buffers/buffer-bytelength-string.js n=4000000 repeat=1 encoding='utf8' type='latin1'                                                                   ***      6.00 %       ±2.33%  ±3.10%  ±4.03%
buffers/buffer-bytelength-string.js n=4000000 repeat=1 encoding='utf8' type='one_byte'                                                                   *      2.60 %       ±2.37%  ±3.16%  ±4.13%
buffers/buffer-bytelength-string.js n=4000000 repeat=16 encoding='utf8' type='one_byte'                                                                ***      7.02 %       ±2.36%  ±3.15%  ±4.11%
buffers/buffer-bytelength-string.js n=4000000 repeat=16 encoding='utf8' type='three_bytes'                                                             ***     -2.19 %       ±0.35%  ±0.46%  ±0.61%
buffers/buffer-bytelength-string.js n=4000000 repeat=16 encoding='utf8' type='two_bytes'                                                               ***     -1.12 %       ±0.37%  ±0.50%  ±0.65%
buffers/buffer-bytelength-string.js n=4000000 repeat=2 encoding='utf8' type='latin1'                                                                   ***      7.54 %       ±2.67%  ±3.58%  ±4.71%
buffers/buffer-bytelength-string.js n=4000000 repeat=2 encoding='utf8' type='one_byte'                                                                 ***      7.61 %       ±2.92%  ±3.89%  ±5.06%
buffers/buffer-bytelength-string.js n=4000000 repeat=2 encoding='utf8' type='two_bytes'                                                                ***     -4.94 %       ±1.09%  ±1.46%  ±1.91%
buffers/buffer-bytelength-string.js n=4000000 repeat=256 encoding='hex' type='four_bytes'                                                                *      4.99 %       ±3.98%  ±5.29%  ±6.89%
buffers/buffer-bytelength-string.js n=4000000 repeat=256 encoding='hex' type='three_bytes'                                                              **      6.60 %       ±3.92%  ±5.22%  ±6.82%
buffers/buffer-bytelength-string.js n=4000000 repeat=256 encoding='utf8' type='three_bytes'                                                            ***     -1.88 %       ±0.27%  ±0.36%  ±0.48%
buffers/buffer-bytelength-string.js n=4000000 repeat=256 encoding='utf8' type='two_bytes'                                                              ***      3.31 %       ±0.27%  ±0.36%  ±0.47%
buffers/buffer-compare-instance-method.js n=1000000 args=1 size=16                                                                                     ***     -5.72 %       ±2.77%  ±3.69%  ±4.80%
buffers/buffer-compare-instance-method.js n=1000000 args=1 size=16386                                                                                  ***     19.59 %       ±2.70%  ±3.60%  ±4.69%
buffers/buffer-compare-instance-method.js n=1000000 args=2 size=16                                                                                      **     -4.91 %       ±2.86%  ±3.81%  ±4.96%
buffers/buffer-compare-instance-method.js n=1000000 args=2 size=16386                                                                                  ***     22.96 %       ±4.01%  ±5.34%  ±6.95%
buffers/buffer-compare-instance-method.js n=1000000 args=2 size=512                                                                                     **     -3.88 %       ±2.50%  ±3.33%  ±4.33%
buffers/buffer-compare-instance-method.js n=1000000 args=5 size=16386                                                                                  ***     16.01 %       ±3.33%  ±4.43%  ±5.78%
buffers/buffer-compare-offset.js n=1000000 size=16 method='offset'                                                                                     ***     -6.05 %       ±2.02%  ±2.69%  ±3.50%
buffers/buffer-compare-offset.js n=1000000 size=16 method='slice'                                                                                      ***     -5.33 %       ±1.41%  ±1.88%  ±2.45%
buffers/buffer-compare-offset.js n=1000000 size=16386 method='offset'                                                                                  ***     -3.98 %       ±1.97%  ±2.63%  ±3.42%
buffers/buffer-compare-offset.js n=1000000 size=16386 method='slice'                                                                                   ***     -3.48 %       ±1.61%  ±2.14%  ±2.79%
buffers/buffer-compare-offset.js n=1000000 size=4096 method='offset'                                                                                    **     -2.66 %       ±2.00%  ±2.66%  ±3.46%
buffers/buffer-compare-offset.js n=1000000 size=4096 method='slice'                                                                                    ***     -3.69 %       ±1.32%  ±1.76%  ±2.29%
buffers/buffer-compare-offset.js n=1000000 size=512 method='offset'                                                                                     **     -2.71 %       ±1.94%  ±2.58%  ±3.37%
buffers/buffer-compare-offset.js n=1000000 size=512 method='slice'                                                                                     ***     -3.36 %       ±1.67%  ±2.22%  ±2.90%
buffers/buffer-compare.js n=1000000 size=16                                                                                                            ***     -4.34 %       ±2.34%  ±3.12%  ±4.07%
buffers/buffer-compare.js n=1000000 size=4096                                                                                                          ***     -5.93 %       ±2.73%  ±3.65%  ±4.79%
buffers/buffer-concat.js n=800000 withTotalLength=0 pieceSize=1 pieces=16                                                                              ***      1.97 %       ±0.97%  ±1.29%  ±1.68%
buffers/buffer-concat.js n=800000 withTotalLength=0 pieceSize=16 pieces=4                                                                               **     -2.56 %       ±1.79%  ±2.38%  ±3.11%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset-length' len=2048 type='Float64Array'                                                        ***    111.53 %       ±0.94%  ±1.26%  ±1.66%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset-length' len=2048 type='Uint16Array'                                                         ***    315.58 %       ±2.18%  ±2.93%  ±3.88%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset-length' len=2048 type='Uint32Array'                                                         ***    105.83 %       ±1.45%  ±1.94%  ±2.56%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset-length' len=2048 type='Uint8Array'                                                          ***    502.89 %       ±4.27%  ±5.75%  ±7.62%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset-length' len=256 type='Float64Array'                                                         ***    495.77 %       ±5.11%  ±6.88%  ±9.13%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset-length' len=256 type='Uint16Array'                                                          ***    668.33 %      ±10.21% ±13.75% ±18.21%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset-length' len=256 type='Uint32Array'                                                          ***    529.14 %       ±5.90%  ±7.95% ±10.54%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset-length' len=256 type='Uint8Array'                                                           ***    715.24 %      ±11.59% ±15.62% ±20.72%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset-length' len=64 type='Float64Array'                                                          ***    658.61 %      ±11.94% ±16.07% ±21.31%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset-length' len=64 type='Uint16Array'                                                           ***    381.71 %       ±8.92% ±12.02% ±15.95%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset-length' len=64 type='Uint32Array'                                                           ***    714.64 %      ±10.43% ±14.04% ±18.63%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset-length' len=64 type='Uint8Array'                                                            ***    392.01 %       ±9.94% ±13.39% ±17.77%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset' len=2048 type='Float64Array'                                                               ***    110.63 %       ±0.61%  ±0.81%  ±1.07%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset' len=2048 type='Uint16Array'                                                                ***    177.96 %       ±2.30%  ±3.09%  ±4.08%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset' len=2048 type='Uint32Array'                                                                ***    115.04 %       ±1.24%  ±1.65%  ±2.17%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset' len=2048 type='Uint8Array'                                                                 ***    377.28 %       ±3.31%  ±4.45%  ±5.90%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset' len=256 type='Float64Array'                                                                ***    376.92 %       ±2.96%  ±3.99%  ±5.28%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset' len=256 type='Uint16Array'                                                                 ***    622.40 %       ±4.45%  ±6.00%  ±7.95%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset' len=256 type='Uint32Array'                                                                 ***    464.10 %       ±3.72%  ±5.00%  ±6.62%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset' len=256 type='Uint8Array'                                                                  ***    750.10 %      ±10.46% ±14.09% ±18.70%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset' len=64 type='Float64Array'                                                                 ***    620.58 %       ±8.95% ±12.06% ±16.00%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset' len=64 type='Uint16Array'                                                                  ***    469.07 %      ±12.18% ±16.41% ±21.78%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset' len=64 type='Uint32Array'                                                                  ***    757.24 %      ±12.28% ±16.54% ±21.93%
buffers/buffer-copy-bytes-from.js n=600000 partial='offset' len=64 type='Uint8Array'                                                                   ***    411.95 %      ±11.87% ±15.99% ±21.21%
buffers/buffer-copy.js n=6000000 partial='true' bytes=1024                                                                                             ***     -5.26 %       ±0.56%  ±0.74%  ±0.97%
buffers/buffer-copy.js n=6000000 partial='true' bytes=128                                                                                              ***     -2.73 %       ±0.36%  ±0.48%  ±0.62%
buffers/buffer-copy.js n=6000000 partial='true' bytes=8                                                                                                ***     -2.55 %       ±0.56%  ±0.75%  ±0.98%
buffers/buffer-creation.js n=600000 len=10 type='fast-alloc'                                                                                             *      5.84 %       ±5.70%  ±7.58%  ±9.87%
buffers/buffer-creation.js n=600000 len=10 type='slow-allocUnsafe'                                                                                       *      6.01 %       ±5.28%  ±7.03%  ±9.17%
buffers/buffer-creation.js n=600000 len=4096 type='fast-allocUnsafe'                                                                                     *      0.95 %       ±0.75%  ±1.00%  ±1.31%
buffers/buffer-creation.js n=600000 len=8192 type='fast-allocUnsafe'                                                                                     *     -0.68 %       ±0.66%  ±0.88%  ±1.14%
buffers/buffer-equals.js n=1000000 difflen='false' size=16386                                                                                           **      5.37 %       ±3.99%  ±5.35%  ±7.06%
buffers/buffer-equals.js n=1000000 difflen='false' size=512                                                                                              *     -1.62 %       ±1.41%  ±1.87%  ±2.44%
buffers/buffer-fill.js n=20000 size=8192 type='fill("t", "ascii")'                                                                                      **     17.70 %      ±12.80% ±17.10% ±22.38%
buffers/buffer-fill.js n=20000 size=8192 type='fill(400)'                                                                                               **      1.91 %       ±1.38%  ±1.84%  ±2.40%
buffers/buffer-from.js n=800000 len=100 source='string-base64'                                                                                          **     -2.92 %       ±1.83%  ±2.45%  ±3.20%
buffers/buffer-from.js n=800000 len=100 source='string'                                                                                                 **      2.66 %       ±1.95%  ±2.60%  ±3.40%
buffers/buffer-from.js n=800000 len=2048 source='string-utf8'                                                                                            *     -0.89 %       ±0.86%  ±1.15%  ±1.50%
buffers/buffer-from.js n=800000 len=2048 source='string'                                                                                                **     -0.87 %       ±0.63%  ±0.84%  ±1.09%
buffers/buffer-hex-decode.js n=1000000 len=64                                                                                                            *     -2.53 %       ±2.02%  ±2.69%  ±3.51%
buffers/buffer-hex-encode.js n=1000000 len=1024                                                                                                         **     -0.28 %       ±0.17%  ±0.23%  ±0.30%
buffers/buffer-hex-encode.js n=1000000 len=64                                                                                                          ***     -1.89 %       ±0.82%  ±1.10%  ±1.43%
buffers/buffer-indexof.js n=50000 type='buffer' encoding='undefined' search='</i> to the Caterpillar'                                                  ***     -0.26 %       ±0.04%  ±0.06%  ±0.07%
buffers/buffer-indexof.js n=50000 type='buffer' encoding='undefined' search='aaaaaaaaaaaaaaaaa'                                                        ***     -0.22 %       ±0.09%  ±0.12%  ±0.16%
buffers/buffer-indexof.js n=50000 type='buffer' encoding='undefined' search='found it very'                                                            ***     -0.40 %       ±0.05%  ±0.07%  ±0.10%
buffers/buffer-indexof.js n=50000 type='buffer' encoding='undefined' search='neighbouring pool'                                                        ***      0.11 %       ±0.06%  ±0.08%  ±0.10%
buffers/buffer-indexof.js n=50000 type='buffer' encoding='undefined' search='Ou est ma chatte?'                                                          *     -0.14 %       ±0.12%  ±0.17%  ±0.22%
buffers/buffer-indexof.js n=50000 type='string' encoding='ascii' search='--l'                                                                          ***      6.51 %       ±2.39%  ±3.19%  ±4.18%
buffers/buffer-indexof.js n=50000 type='string' encoding='ascii' search='@'                                                                            ***     38.55 %       ±4.45%  ±5.94%  ±7.76%
buffers/buffer-indexof.js n=50000 type='string' encoding='ascii' search='</i> to the Caterpillar'                                                        *      3.57 %       ±2.92%  ±3.88%  ±5.06%
buffers/buffer-indexof.js n=50000 type='string' encoding='ascii' search='aaaaaaaaaaaaaaaaa'                                                            ***      5.96 %       ±3.01%  ±4.01%  ±5.22%
buffers/buffer-indexof.js n=50000 type='string' encoding='ascii' search='Alice'                                                                        ***     56.73 %       ±6.42%  ±8.55% ±11.12%
buffers/buffer-indexof.js n=50000 type='string' encoding='ascii' search='found it very'                                                                 **      1.92 %       ±1.36%  ±1.81%  ±2.36%
buffers/buffer-indexof.js n=50000 type='string' encoding='ascii' search='Gryphon'                                                                      ***      6.10 %       ±1.49%  ±1.99%  ±2.61%
buffers/buffer-indexof.js n=50000 type='string' encoding='ascii' search='Ou est ma chatte?'                                                            ***      1.10 %       ±0.22%  ±0.29%  ±0.39%
buffers/buffer-indexof.js n=50000 type='string' encoding='ascii' search='SQ'                                                                           ***     11.79 %       ±3.62%  ±4.81%  ±6.27%
buffers/buffer-indexof.js n=50000 type='string' encoding='ascii' search='venture to go near the house till she had brought herself down to'            ***      7.42 %       ±3.75%  ±4.99%  ±6.51%
buffers/buffer-indexof.js n=50000 type='string' encoding='latin1' search='--l'                                                                           *     -2.06 %       ±1.73%  ±2.33%  ±3.07%
buffers/buffer-indexof.js n=50000 type='string' encoding='latin1' search='aaaaaaaaaaaaaaaaa'                                                             *     -1.60 %       ±1.55%  ±2.09%  ±2.77%
buffers/buffer-indexof.js n=50000 type='string' encoding='latin1' search='neighbouring pool'                                                             *     -2.25 %       ±2.10%  ±2.80%  ±3.65%
buffers/buffer-indexof.js n=50000 type='string' encoding='ucs2' search='@'                                                                               *      7.06 %       ±5.60%  ±7.45%  ±9.70%
buffers/buffer-indexof.js n=50000 type='string' encoding='utf8' search='SQ'                                                                            ***     -9.21 %       ±2.54%  ±3.40%  ±4.45%
buffers/buffer-isutf8.js input='∀x∈ℝ: ⌈x⌉ = −⌊−x⌋' length='long' n=20000000                                                                            ***      0.28 %       ±0.09%  ±0.13%  ±0.17%
buffers/buffer-isutf8.js input='regular string' length='short' n=20000000                                                                                *      0.45 %       ±0.42%  ±0.57%  ±0.74%
buffers/buffer-normalize-encoding.js n=1000000 encoding='UCS-2'                                                                                          *     -4.48 %       ±3.82%  ±5.09%  ±6.63%
buffers/buffer-normalize-encoding.js n=1000000 encoding='utf8'                                                                                           *      0.77 %       ±0.69%  ±0.93%  ±1.21%
buffers/buffer-read-float.js n=1000000 value='small' endian='LE' type='Double'                                                                           *     17.66 %      ±14.64% ±19.49% ±25.39%
buffers/buffer-read-with-byteLength.js byteLength=1 n=1000000 type='UIntLE' buffer='fast'                                                                *    -11.93 %      ±11.27% ±15.01% ±19.55%
buffers/buffer-read-with-byteLength.js byteLength=3 n=1000000 type='IntLE' buffer='fast'                                                                **    -16.35 %      ±10.73% ±14.31% ±18.67%
buffers/buffer-read-with-byteLength.js byteLength=3 n=1000000 type='UIntLE' buffer='fast'                                                                *      7.97 %       ±7.04%  ±9.48% ±12.59%
buffers/buffer-read-with-byteLength.js byteLength=6 n=1000000 type='UIntBE' buffer='fast'                                                                *    -11.12 %       ±8.63% ±11.53% ±15.10%
buffers/buffer-read.js n=1000000 type='BigInt64BE' buffer='fast'                                                                                       ***    -11.13 %       ±6.38%  ±8.49% ±11.06%
buffers/buffer-read.js n=1000000 type='BigUInt64BE' buffer='fast'                                                                                        *    -17.84 %      ±14.37% ±19.12% ±24.90%
buffers/buffer-read.js n=1000000 type='UInt8' buffer='fast'                                                                                              *    -15.47 %      ±14.86% ±19.78% ±25.76%
buffers/buffer-swap.js n=1000000 len=1024 method='swap16' aligned='false'                                                                              ***      7.68 %       ±2.75%  ±3.67%  ±4.81%
buffers/buffer-swap.js n=1000000 len=1024 method='swap16' aligned='true'                                                                               ***      7.53 %       ±3.18%  ±4.25%  ±5.59%
buffers/buffer-swap.js n=1000000 len=1024 method='swap32' aligned='false'                                                                              ***     12.40 %       ±0.39%  ±0.53%  ±0.68%
buffers/buffer-swap.js n=1000000 len=1024 method='swap32' aligned='true'                                                                               ***     12.84 %       ±0.38%  ±0.50%  ±0.65%
buffers/buffer-swap.js n=1000000 len=1024 method='swap64' aligned='false'                                                                              ***     19.93 %       ±0.61%  ±0.81%  ±1.06%
buffers/buffer-swap.js n=1000000 len=1024 method='swap64' aligned='true'                                                                               ***     20.88 %       ±0.61%  ±0.82%  ±1.07%
buffers/buffer-swap.js n=1000000 len=2056 method='swap16' aligned='false'                                                                              ***     10.70 %       ±0.61%  ±0.82%  ±1.06%
buffers/buffer-swap.js n=1000000 len=2056 method='swap16' aligned='true'                                                                               ***     11.85 %       ±0.98%  ±1.31%  ±1.74%
buffers/buffer-swap.js n=1000000 len=2056 method='swap32' aligned='false'                                                                              ***      5.90 %       ±0.19%  ±0.25%  ±0.33%
buffers/buffer-swap.js n=1000000 len=2056 method='swap32' aligned='true'                                                                               ***      6.08 %       ±0.19%  ±0.25%  ±0.32%
buffers/buffer-swap.js n=1000000 len=2056 method='swap64' aligned='false'                                                                              ***     12.26 %       ±0.33%  ±0.44%  ±0.57%
buffers/buffer-swap.js n=1000000 len=2056 method='swap64' aligned='true'                                                                               ***     13.15 %       ±0.32%  ±0.43%  ±0.56%
buffers/buffer-swap.js n=1000000 len=256 method='swap16' aligned='false'                                                                               ***     39.19 %       ±1.05%  ±1.40%  ±1.83%
buffers/buffer-swap.js n=1000000 len=256 method='swap16' aligned='true'                                                                                ***     39.18 %       ±1.18%  ±1.57%  ±2.06%
buffers/buffer-swap.js n=1000000 len=256 method='swap32' aligned='false'                                                                               ***      9.78 %       ±1.04%  ±1.39%  ±1.81%
buffers/buffer-swap.js n=1000000 len=256 method='swap32' aligned='true'                                                                                ***     10.84 %       ±1.46%  ±1.95%  ±2.55%
buffers/buffer-swap.js n=1000000 len=256 method='swap64' aligned='false'                                                                               ***     35.94 %       ±1.57%  ±2.10%  ±2.75%
buffers/buffer-swap.js n=1000000 len=256 method='swap64' aligned='true'                                                                                ***     38.52 %       ±1.39%  ±1.85%  ±2.40%
buffers/buffer-swap.js n=1000000 len=64 method='swap16' aligned='false'                                                                                ***     89.56 %       ±1.36%  ±1.81%  ±2.37%
buffers/buffer-swap.js n=1000000 len=64 method='swap16' aligned='true'                                                                                 ***     91.53 %       ±4.71%  ±6.33%  ±8.35%
buffers/buffer-swap.js n=1000000 len=64 method='swap32' aligned='false'                                                                                ***     43.55 %       ±1.77%  ±2.38%  ±3.15%
buffers/buffer-swap.js n=1000000 len=64 method='swap32' aligned='true'                                                                                 ***     37.37 %       ±2.25%  ±3.02%  ±4.01%
buffers/buffer-swap.js n=1000000 len=64 method='swap64' aligned='false'                                                                                ***     61.56 %       ±1.20%  ±1.61%  ±2.10%
buffers/buffer-swap.js n=1000000 len=64 method='swap64' aligned='true'                                                                                 ***     60.75 %       ±1.58%  ±2.10%  ±2.75%
buffers/buffer-swap.js n=1000000 len=768 method='swap16' aligned='false'                                                                               ***      5.86 %       ±2.19%  ±2.91%  ±3.79%
buffers/buffer-swap.js n=1000000 len=768 method='swap32' aligned='false'                                                                               ***     16.96 %       ±0.63%  ±0.83%  ±1.09%
buffers/buffer-swap.js n=1000000 len=768 method='swap32' aligned='true'                                                                                ***     17.22 %       ±0.78%  ±1.03%  ±1.35%
buffers/buffer-swap.js n=1000000 len=768 method='swap64' aligned='false'                                                                               ***     22.20 %       ±1.01%  ±1.35%  ±1.77%
buffers/buffer-swap.js n=1000000 len=768 method='swap64' aligned='true'                                                                                ***     23.60 %       ±0.80%  ±1.07%  ±1.41%
buffers/buffer-swap.js n=1000000 len=8192 method='swap16' aligned='false'                                                                              ***      6.96 %       ±0.21%  ±0.28%  ±0.36%
buffers/buffer-swap.js n=1000000 len=8192 method='swap16' aligned='true'                                                                               ***      6.80 %       ±0.24%  ±0.31%  ±0.41%
buffers/buffer-swap.js n=1000000 len=8192 method='swap32' aligned='false'                                                                              ***      1.62 %       ±0.06%  ±0.08%  ±0.11%
buffers/buffer-swap.js n=1000000 len=8192 method='swap32' aligned='true'                                                                               ***      1.58 %       ±0.05%  ±0.07%  ±0.09%
buffers/buffer-swap.js n=1000000 len=8192 method='swap64' aligned='false'                                                                              ***      3.92 %       ±0.11%  ±0.15%  ±0.20%
buffers/buffer-swap.js n=1000000 len=8192 method='swap64' aligned='true'                                                                               ***      4.00 %       ±0.08%  ±0.11%  ±0.14%
buffers/buffer-tojson.js len=4096 n=10000                                                                                                              ***      9.30 %       ±2.13%  ±2.83%  ±3.69%
buffers/buffer-tostring.js n=1000000 len=1 args=0 encoding=''                                                                                          ***     -5.78 %       ±2.17%  ±2.88%  ±3.75%
buffers/buffer-tostring.js n=1000000 len=1 args=1 encoding='ascii'                                                                                     ***     -6.28 %       ±3.59%  ±4.78%  ±6.23%
buffers/buffer-tostring.js n=1000000 len=1 args=1 encoding='base64'                                                                                    ***     -3.49 %       ±1.84%  ±2.46%  ±3.21%
buffers/buffer-tostring.js n=1000000 len=1 args=1 encoding='base64url'                                                                                 ***     -2.32 %       ±1.23%  ±1.64%  ±2.13%
buffers/buffer-tostring.js n=1000000 len=1 args=1 encoding='hex'                                                                                        **     -3.18 %       ±2.26%  ±3.01%  ±3.92%
buffers/buffer-tostring.js n=1000000 len=1 args=1 encoding='latin1'                                                                                      *     -4.00 %       ±3.30%  ±4.39%  ±5.72%
buffers/buffer-tostring.js n=1000000 len=1 args=1 encoding='UCS-2'                                                                                     ***     -3.53 %       ±1.63%  ±2.17%  ±2.82%
buffers/buffer-tostring.js n=1000000 len=1 args=1 encoding='utf8'                                                                                      ***     -5.49 %       ±2.82%  ±3.76%  ±4.90%
buffers/buffer-tostring.js n=1000000 len=1 args=3 encoding='ascii'                                                                                     ***     -5.43 %       ±2.52%  ±3.35%  ±4.36%
buffers/buffer-tostring.js n=1000000 len=1 args=3 encoding='base64url'                                                                                 ***     -5.09 %       ±1.79%  ±2.38%  ±3.10%
buffers/buffer-tostring.js n=1000000 len=1 args=3 encoding='hex'                                                                                         *     -3.23 %       ±2.89%  ±3.86%  ±5.04%
buffers/buffer-tostring.js n=1000000 len=1 args=3 encoding='latin1'                                                                                    ***     -8.27 %       ±3.20%  ±4.26%  ±5.54%
buffers/buffer-tostring.js n=1000000 len=1 args=3 encoding='UCS-2'                                                                                     ***     -5.43 %       ±1.58%  ±2.10%  ±2.74%
buffers/buffer-tostring.js n=1000000 len=1 args=3 encoding='utf8'                                                                                      ***     -6.62 %       ±2.83%  ±3.76%  ±4.89%
buffers/buffer-tostring.js n=1000000 len=1024 args=1 encoding='ascii'                                                                                  ***     -2.48 %       ±0.88%  ±1.18%  ±1.53%
buffers/buffer-tostring.js n=1000000 len=1024 args=1 encoding='UCS-2'                                                                                  ***     -1.79 %       ±0.98%  ±1.31%  ±1.70%
buffers/buffer-tostring.js n=1000000 len=1024 args=1 encoding='utf8'                                                                                    **     -2.00 %       ±1.33%  ±1.78%  ±2.32%
buffers/buffer-tostring.js n=1000000 len=1024 args=3 encoding='ascii'                                                                                  ***     -2.42 %       ±1.04%  ±1.38%  ±1.80%
buffers/buffer-tostring.js n=1000000 len=1024 args=3 encoding='hex'                                                                                      *      0.59 %       ±0.55%  ±0.73%  ±0.95%
buffers/buffer-tostring.js n=1000000 len=64 args=0 encoding=''                                                                                         ***     -4.26 %       ±2.32%  ±3.09%  ±4.03%
buffers/buffer-tostring.js n=1000000 len=64 args=1 encoding='ascii'                                                                                    ***     -5.35 %       ±1.80%  ±2.40%  ±3.12%
buffers/buffer-tostring.js n=1000000 len=64 args=1 encoding='base64url'                                                                                ***     -3.90 %       ±1.96%  ±2.62%  ±3.41%
buffers/buffer-tostring.js n=1000000 len=64 args=1 encoding='hex'                                                                                      ***     -5.93 %       ±2.14%  ±2.84%  ±3.70%
buffers/buffer-tostring.js n=1000000 len=64 args=1 encoding='latin1'                                                                                   ***     -4.81 %       ±2.36%  ±3.14%  ±4.08%
buffers/buffer-tostring.js n=1000000 len=64 args=1 encoding='UCS-2'                                                                                    ***     -3.89 %       ±1.10%  ±1.47%  ±1.91%
buffers/buffer-tostring.js n=1000000 len=64 args=1 encoding='utf8'                                                                                     ***     -3.85 %       ±2.15%  ±2.87%  ±3.75%
buffers/buffer-tostring.js n=1000000 len=64 args=3 encoding='ascii'                                                                                    ***     -5.52 %       ±1.83%  ±2.44%  ±3.17%
buffers/buffer-tostring.js n=1000000 len=64 args=3 encoding='base64'                                                                                    **      2.72 %       ±1.64%  ±2.19%  ±2.85%
buffers/buffer-tostring.js n=1000000 len=64 args=3 encoding='base64url'                                                                                 **     -3.42 %       ±2.04%  ±2.71%  ±3.53%
buffers/buffer-tostring.js n=1000000 len=64 args=3 encoding='hex'                                                                                      ***     -7.50 %       ±1.63%  ±2.17%  ±2.82%
buffers/buffer-tostring.js n=1000000 len=64 args=3 encoding='latin1'                                                                                   ***     -7.08 %       ±1.81%  ±2.41%  ±3.14%
buffers/buffer-tostring.js n=1000000 len=64 args=3 encoding='UCS-2'                                                                                     **     -2.23 %       ±1.38%  ±1.84%  ±2.41%
buffers/buffer-tostring.js n=1000000 len=64 args=3 encoding='utf8'                                                                                     ***     -8.16 %       ±1.60%  ±2.13%  ±2.78%
buffers/buffer-transcode.js n=100000 length=1 toEncoding='ascii' fromEncoding='ascii'                                                                  ***      2.30 %       ±0.95%  ±1.27%  ±1.65%
buffers/buffer-transcode.js n=100000 length=1 toEncoding='ascii' fromEncoding='ucs2'                                                                     *      1.84 %       ±1.74%  ±2.32%  ±3.02%
buffers/buffer-transcode.js n=100000 length=10 toEncoding='utf8' fromEncoding='utf8'                                                                     *      1.95 %       ±1.71%  ±2.27%  ±2.96%
buffers/buffer-transcode.js n=100000 length=1000 toEncoding='ascii' fromEncoding='ascii'                                                               ***      2.20 %       ±1.04%  ±1.39%  ±1.81%
buffers/buffer-transcode.js n=100000 length=1000 toEncoding='ascii' fromEncoding='latin1'                                                               **      1.87 %       ±1.10%  ±1.47%  ±1.91%
buffers/buffer-transcode.js n=100000 length=1000 toEncoding='ascii' fromEncoding='ucs2'                                                                ***      2.84 %       ±0.22%  ±0.30%  ±0.39%
buffers/buffer-transcode.js n=100000 length=1000 toEncoding='ascii' fromEncoding='utf8'                                                                 **      2.05 %       ±1.33%  ±1.77%  ±2.31%
buffers/buffer-transcode.js n=100000 length=1000 toEncoding='latin1' fromEncoding='latin1'                                                              **      1.80 %       ±1.06%  ±1.41%  ±1.84%
buffers/buffer-transcode.js n=100000 length=1000 toEncoding='latin1' fromEncoding='ucs2'                                                               ***      2.81 %       ±0.18%  ±0.24%  ±0.32%
buffers/buffer-transcode.js n=100000 length=1000 toEncoding='ucs2' fromEncoding='ucs2'                                                                 ***     -1.39 %       ±0.56%  ±0.74%  ±0.96%
buffers/buffer-transcode.js n=100000 length=1000 toEncoding='ucs2' fromEncoding='utf8'                                                                  **      1.02 %       ±0.67%  ±0.89%  ±1.16%
buffers/buffer-write-string-short.js n=1000000 len=1 encoding='ascii'                                                                                    *      3.90 %       ±3.16%  ±4.21%  ±5.50%
buffers/buffer-write-string-short.js n=1000000 len=1 encoding='utf8'                                                                                   ***      5.73 %       ±3.21%  ±4.28%  ±5.57%
buffers/buffer-write-string-short.js n=1000000 len=16 encoding='ascii'                                                                                  **      5.44 %       ±4.05%  ±5.39%  ±7.02%
buffers/buffer-write-string-short.js n=1000000 len=16 encoding='latin1'                                                                                 **      6.46 %       ±4.50%  ±5.99%  ±7.80%
buffers/buffer-write-string-short.js n=1000000 len=32 encoding='latin1'                                                                                  *      4.44 %       ±3.41%  ±4.53%  ±5.90%
buffers/buffer-write-string-short.js n=1000000 len=32 encoding='utf8'                                                                                    *      3.50 %       ±3.23%  ±4.29%  ±5.59%
buffers/buffer-write-string-short.js n=1000000 len=8 encoding='latin1'                                                                                  **      4.93 %       ±3.41%  ±4.54%  ±5.91%
buffers/buffer-write-string.js n=1000000 len=2048 args='' encoding=''                                                                                    *      2.29 %       ±1.85%  ±2.48%  ±3.26%
buffers/buffer-write-string.js n=1000000 len=2048 args='' encoding='ascii'                                                                             ***     -7.09 %       ±1.00%  ±1.33%  ±1.74%
buffers/buffer-write-string.js n=1000000 len=2048 args='' encoding='hex'                                                                               ***      1.07 %       ±0.34%  ±0.45%  ±0.60%
buffers/buffer-write-string.js n=1000000 len=2048 args='' encoding='latin1'                                                                            ***      4.33 %       ±1.81%  ±2.41%  ±3.14%
buffers/buffer-write-string.js n=1000000 len=2048 args='' encoding='utf16le'                                                                           ***      4.00 %       ±1.47%  ±1.95%  ±2.54%
buffers/buffer-write-string.js n=1000000 len=2048 args='offset' encoding='ascii'                                                                        **     -3.95 %       ±2.81%  ±3.74%  ±4.87%
buffers/buffer-write-string.js n=1000000 len=2048 args='offset' encoding='utf16le'                                                                     ***      5.76 %       ±2.92%  ±3.89%  ±5.06%
buffers/buffer-write-string.js n=1000000 len=2048 args='offset+length' encoding='hex'                                                                  ***      1.55 %       ±0.45%  ±0.60%  ±0.79%
buffers/buffer-write-string.js n=1000000 len=2048 args='offset+length' encoding='utf16le'                                                              ***      4.65 %       ±2.22%  ±2.96%  ±3.85%
buffers/buffer-write-string.js n=1000000 len=2048 args='offset+length' encoding='utf8'                                                                  **      3.10 %       ±2.05%  ±2.74%  ±3.57%
buffers/buffer-write.js n=1000000 type='BigUInt64BE' buffer='fast'                                                                                       *     -1.82 %       ±1.58%  ±2.10%  ±2.73%
buffers/dataview-set.js n=1000000 type='Int32LE'                                                                                                         *      3.74 %       ±3.25%  ±4.34%  ±5.67%
  29.15 false positives, when considering a   5% risk acceptance (*, **, ***),
  5.83 false positives, when considering a   1% risk acceptance (**, ***),
  0.58 false positives, when considering a 0.1% risk acceptance (***)


function fromArrayLike(obj) {
if (obj.length <= 0)
const { length } = obj;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not move this to line 553? Can you also add a JSDoc?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anonrig you mean something like when you said move to line 553?

 // Before                   
  fromArrayLike(obj);
  // After
  fromArrayLike(obj, obj.length);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fromArrayLike({ length })

lib/buffer.js Outdated
if (length === undefined && typeof offset === 'string') {
encoding = offset;
length = this.length;
length = len;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is extremely confusing. Please use more readable variable names.

Comment on lines +1217 to 1219
const data = new Array(len);
for (let i = 0; i < len; ++i)
data[i] = this[i];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be simplified into a single line.

Array.from({ length: this.length }, (_, i) => this[i]);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Classic for loop is likely more performant, no?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure anymore


Buffer.prototype.swap16 = function swap16() {
// For Buffer.length < 128, it's generally faster to
// For Buffer.length <= 32, it's generally faster to
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a reference link to this pull-request above this line

void Swap16(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]);
DCHECK(args[0]->IsArrayBufferView());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although I agree that DCHECK is sufficient here, we always use non-debug CHECK's. If we want to replace this, we should do it in all of the codebase.

Suggested change
DCHECK(args[0]->IsArrayBufferView());
CHECK(args[0]->IsArrayBufferView());

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we already haveSPREAD_BUFFER_ARG for Check thenDCheck looks redudand want me to remove this?

FastApiCallbackOptions& options) {
TRACK_V8_FAST_API_CALL("buffer.swap16");
HandleScope scope(options.isolate);
SPREAD_BUFFER_ARG(buffer_obj, ts_obj);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fast api call is missing DCHECK(buffer_obj->IsArrayBufferView());

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SPREAD_BUFFER_ARG already do CHECK((val)->IsArrayBufferView()); which is why I didn't add DCheck here

void Swap32(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]);
DCHECK(args[0]->IsArrayBufferView());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
DCHECK(args[0]->IsArrayBufferView());
CHECK(args[0]->IsArrayBufferView());

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above comment

FastApiCallbackOptions& options) {
TRACK_V8_FAST_API_CALL("buffer.swap32");
HandleScope scope(options.isolate);
SPREAD_BUFFER_ARG(buffer_obj, ts_obj);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check is arraybufferview is missing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SPREAD_BUFFER_ARG already do CHECK((val)->IsArrayBufferView()); which is why I didn't add DCheck here

FastApiCallbackOptions& options) {
TRACK_V8_FAST_API_CALL("buffer.swap64");
HandleScope scope(options.isolate);
SPREAD_BUFFER_ARG(buffer_obj, ts_obj);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check is arraybufferview is missing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

void Swap64(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]);
DCHECK(args[0]->IsArrayBufferView());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
DCHECK(args[0]->IsArrayBufferView());
CHECK(args[0]->IsArrayBufferView());

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as older comment

thisalihassan and others added 10 commits March 21, 2026 09:31
- copyBytesFrom: calculate byte offsets directly instead of
  slicing into an intermediate typed array
- toString('hex'): use V8 Uint8Array.prototype.toHex() builtin
- fill: add single-char ASCII fast path
- indexOf: use indexOfString directly for ASCII encoding
- swap16/32/64: add V8 Fast API functions
- Guard ensureUint8ArrayToHex against --no-js-base-64 flag by
  falling back to C++ hexSlice when toHex is unavailable
- Remove THROW_AND_RETURN_UNLESS_BUFFER and return value from
  slow Swap16/32/64 to match fast path conventions (JS validates)
- Add TRACK_V8_FAST_API_CALL to FastSwap16/32/64
- Add test/parallel/test-buffer-swap-fast.js for fast API verification
Remove V8 Uint8Array.prototype.toHex() path for Buffer.toString('hex')
in favour of the upcoming nbytes HexEncode improvement (nodejs/nbytes#12)
which is ~3x faster through the existing C++ hexSlice path.

Refs: nodejs/nbytes#12
Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
@thisalihassan thisalihassan force-pushed the buffer-perf-improvements branch from 1d16ad4 to f1d938b Compare March 21, 2026 04:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author ready PRs that have at least one approval, no pending requests for changes, and a CI started. buffer Issues and PRs related to the buffer subsystem. c++ Issues and PRs that require attention from people who are familiar with C++. needs-benchmark-ci PR that need a benchmark CI run. needs-ci PRs that need a full CI run. performance Issues and PRs related to the performance of Node.js.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants